﻿using Microsoft.AspNetCore.Authentication;
using Microsoft.AspNetCore.Http;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.Logging;
using Newtonsoft.Json;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Security.Claims;
using System.Text;
using System.Threading.Tasks;

namespace OnWork.Admin.Util.Base
{
    public class MyAuthHandler : IAuthenticationHandler
    {
        public const string SchemeName = "MyAuth";

        private AuthenticationScheme _scheme;
        private HttpContext _context;
        private readonly ILogger _logger;
        private readonly JWTOptions _JWTOptions;

        public MyAuthHandler(ILogger<MyAuthHandler> logger, IConfiguration configuration)
        {
            _logger = logger;
            _JWTOptions = configuration.GetSection(JWTOptions.JWT).Get<JWTOptions>();
        }

        /// <summary>
        /// 初始化认证
        /// </summary>
        public Task InitializeAsync(AuthenticationScheme scheme, HttpContext context)
        {
            _scheme = scheme;
            _context = context;
            return Task.CompletedTask;
        }

        /// <summary>
        /// 认证处理
        /// </summary>
        public Task<AuthenticateResult> AuthenticateAsync()
        {
            try
            {
                //如果配置为fasle 则直接返回成功
                if (_JWTOptions.Enable == false)
                {
                    var ticket = GetAuthTicket("dev", "No");
                    return Task.FromResult(AuthenticateResult.Success(ticket));
                }

                //userToken 关键字
                string userTokenKey = "usertoken";
                var req = _context.Request.Query;
                var userToken = req[userTokenKey].FirstOrDefault();
                string userToeknHeader = null;
                //获取Header里的user
                if (_context.Request.Headers.Keys.Contains(userTokenKey))
                {
                    userToeknHeader = _context.Request.Headers[userTokenKey];
                }
                //没有userTokenKey 则直接返回
                if (string.IsNullOrEmpty(userToken) && string.IsNullOrEmpty(userToeknHeader))
                {
                    return Task.FromResult(AuthenticateResult.Fail("认证失败!"));
                }

                //验证UerToekn是否正确
                //如果usertoken为空则取值header的token
                if (string.IsNullOrEmpty(userToken))
                {
                    userToken = userToeknHeader;
                }

                bool isPassed = JWT.CheckTokenByDate(userToken, out var jWT_TokenUser);
                if (isPassed)
                {
                    //获取时间
                    var dtJwt = DateTime.Parse(jWT_TokenUser.dt);
                    //和当前时间相差多少分钟
                    var mintus = (DateTime.Now - dtJwt).TotalMinutes;
                    //token如果小于1天则认为是成功的
                    if (mintus < _JWTOptions.ExpMinutes)
                    {
                        var ticket = GetAuthTicket(jWT_TokenUser.id, jWT_TokenUser.dt);
                        return Task.FromResult(AuthenticateResult.Success(ticket));
                    }
                }
                return Task.FromResult(AuthenticateResult.Fail("认证失败!"));
            }
            catch (Exception ex)
            {
                _logger.LogError(ex, ex.Message);
                return Task.FromResult(AuthenticateResult.Fail("认证失败!"));
            }
        }

        AuthenticationTicket GetAuthTicket(string name, string role)
        {
            var claimsIdentity = new ClaimsIdentity(new Claim[]
            {
                new Claim(ClaimTypes.Name, name),
                new Claim(ClaimTypes.Role, role),
            }, "My_Auth");
            var principal = new ClaimsPrincipal(claimsIdentity);
            return new AuthenticationTicket(principal, _scheme.Name);
        }

        /// <summary>
        /// 权限不足时的处理
        /// </summary>
        public Task ForbidAsync(AuthenticationProperties properties)
        {
            _context.Response.StatusCode = (int)HttpStatusCode.Forbidden;
            return Task.CompletedTask;
        }

        /// <summary>
        /// 未登录时的处理
        /// </summary>
        public async Task ChallengeAsync(AuthenticationProperties properties)
        {
            //_context.Response.StatusCode = (int)HttpStatusCode.Unauthorized;
            _context.Response.ContentType = "application/json";
            var berrs = new ReturnModel() { Code = (int)HttpStatusCode.Unauthorized, Msg = "usertoken无效或过期!", Data = "Unauthorized" };
            string json = JsonConvert.SerializeObject(berrs);
            var data = Encoding.UTF8.GetBytes(json);
            await _context.Response.Body.WriteAsync(data);
        }
    }
}